/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once


//#include "JIT.h"
#include "JIT_Def.h"
//#include <llvm/ADT/OwningPtr.h>



#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/Interpreter.h>


#include <llvm/IR/IRBuilder.h>



//#include <llvm/ExecutionEngine/Orc/ExecutionUtils.h>
//#include <llvm/ExecutionEngine/Orc/IRCompileLayer.h>
//#include <llvm/ExecutionEngine/Orc/IRTransformLayer.h>
//#include <llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h>
//#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
//#include <llvm/ExecutionEngine/Orc/TargetProcessControl.h>



/*#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/TargetSelect.h"
#include <llvm/Support/MemoryBuffer.h>
#include "llvm/Support/raw_ostream.h"
#include <llvm/Support/DynamicLibrary.h>
#include "llvm/Support/Debug.h"
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/FileSystem.h>*/
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TargetRegistry.h"



//#include "llvm/ADT/OwningPtr.h"
//#include <llvm/ExecutionEngine/MCJIT.h>





#include <memory>








/*namespace llvm {
namespace orc {

	class KaleidoscopeJIT {
	private:
		ExecutionSession ES;
		RTDyldObjectLinkingLayer ObjectLayer;
		IRCompileLayer CompileLayer;

		DataLayout DL;
		MangleAndInterner Mangle;
		ThreadSafeContext Ctx;

	public:
		KaleidoscopeJIT(JITTargetMachineBuilder JTMB, DataLayout DL)
			: ObjectLayer(ES,
				[]() { return std::make_unique<SectionMemoryManager>(); }),
			CompileLayer(ES, ObjectLayer, ConcurrentIRCompiler(std::move(JTMB))),
			DL(std::move(DL)), Mangle(ES, this->DL),
			Ctx(std::make_unique<LLVMContext>()) 
		{
			//ES.getMainJITDylib().setGenerator(cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(DL)));
		}


		static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
			auto JTMB = JITTargetMachineBuilder::detectHost();

			if (!JTMB)
				return JTMB.takeError();

			auto DL = JTMB->getDefaultDataLayoutForTarget();
			if (!DL)
				return DL.takeError();

			return std::make_unique<KaleidoscopeJIT>(std::move(*JTMB), std::move(*DL));
		}

		const DataLayout& getDataLayout() const { return DL; }

		LLVMContext& getContext() { return *Ctx.getContext(); }


		void addModule(std::unique_ptr<Module> M) {
			cantFail(CompileLayer.add(ES.getMainJITDylib(),
				ThreadSafeModule(std::move(M), Ctx)));
		}

		Expected<JITEvaluatedSymbol> lookup(StringRef Name) {
			return ES.lookup({ &ES.getMainJITDylib() }, Mangle(Name.str()));
		}
	};


	}
}*/

typedef struct {
	llvm::Function* pFunc;
	llvm::BasicBlock* pBlock;
}S_函数IR块;


struct S_LLVM模块 {
	llvm::ExecutionEngine*			m_运行引擎;
	std::unique_ptr<llvm::Module>	m_模块_愚蠢的需求设计;
	llvm::Module*					m_模块;

	llvm::IRBuilder<>				m_Builder;

	S_LLVM模块();
};


//bool f_llvm_初始化JIT引擎(std::unique_ptr<llvm::Module> 模块);
bool f_llvm_初始化JIT引擎();
bool f_llvm_清理JIT引擎();

void f_llvm_构建机器码();

llvm::LLVMContext&	f_llvm_构建环境();
llvm::Module*		f_llvm_模块();
uint32				f_llvm_创建程序集();
void				f_llvm_卸载程序(S_LLVM模块* model);


llvm::Module*	f_llvm_创建程序集(const std::string& path);
void            f_llvm_销毁程序集(llvm::Module* module);
uint64			f_llvm_从程序集取函数指针(const std::string& funName);
bool			f_llvm_执行函数(const std::string& funName, llvm::ExecutionEngine* 执行引擎, std::vector<E_JIT_FunParam>& 参数);

void            f_llvm_添加全局变量(const std::string& 全局变量名称, uint64 全局变量值);


llvm::Value* f_llvm_构建i8变量(llvm::LLVMContext& ctx, llvm::BasicBlock* block, int32 初始值, std::string 名称);
llvm::Value* f_llvm_构建i16变量(llvm::LLVMContext& ctx, llvm::BasicBlock* block, int32 初始值, std::string 名称);
llvm::Value* f_llvm_构建i32变量(llvm::LLVMContext& ctx, llvm::BasicBlock* block, int32 初始值, std::string 名称);
llvm::Value* f_llvm_构建变量(llvm::LLVMContext& ctx, llvm::BasicBlock* block, E_值类型 type, int64 初始值, bool 是否有符合);
llvm::Type* f_llvm_构建类型(llvm::LLVMContext& ctx, E_值类型 type, std::string& name);
Inline llvm::Value* f_llvm_构建i32常量(llvm::LLVMContext& ctx, int32 初始值) {
	return llvm::ConstantInt::get(llvm::Type::getInt32Ty(ctx), 初始值);
}

llvm::AllocaInst* f_llvm_构建f32变量(llvm::LLVMContext& ctx, llvm::BasicBlock* block, int32 初始值);
Inline llvm::Value* f_llvm_构建f32常量(llvm::LLVMContext& ctx, float32 初始值) {
	return llvm::ConstantFP::get(llvm::Type::getFloatTy(ctx), 初始值);
}
Inline llvm::Value* f_llvm_构建f64常量(llvm::LLVMContext& ctx, float32 初始值) {
	return llvm::ConstantFP::get(llvm::Type::getDoubleTy(ctx), 初始值);
}


S_函数IR块 f_llvm_构建函数声明(std::string name, std::vector<llvm::Type*>& 参数类型, llvm::Type* 返回类型, bool 是否有常量);

void f_llvm_构建返回值(S_函数IR块& block, llvm::Value* pRetVal, std::string 函数名称);





llvm::Value* f_llvm_构建算术运算符L1IR(const std::vector<S_操作符表达段>& 运算符);
llvm::Value* f_llvm_构建算术运算符L1IR(llvm::Value* 计算数, E_运算符 op);
llvm::Value* f_llvm_构建算术运算符L2IR(llvm::Value* 计算数, E_运算符 op);
llvm::Value* f_llvm_构建算术运算符L3IR(llvm::Value* 计算数, E_运算符 op);
llvm::Value* f_llvm_构建算术运算符L4IR(llvm::Value* 计算数, E_运算符 op);
llvm::Value* f_llvm_构建算术运算符L5IR(llvm::Value* 计算数, E_运算符 op);

llvm::Value* f_llvm_构建乘除运算符IR(llvm::Value* 计算数L, llvm::Value* 计算数R, E_运算符 op);
llvm::Value* f_llvm_构建加减运算符IR(llvm::Value* 计算数L, llvm::Value* 计算数R, E_运算符 op);
llvm::Value* f_llvm_构建位移运算符IR(llvm::Value* 计算数L, llvm::Value* 计算数R, E_运算符 op);
llvm::Value* f_llvm_构建赋值运算符IR(llvm::Value* 计算数L, llvm::Value* 计算数R, E_运算符 op);



